﻿using Kenly.DBFramework.Gateway;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using System;
using System.Collections;
using System.Collections.Generic;
using Kenly.DBFramework.TestModel.Purchasing;

namespace Kenly.DBFramework.Tests
{


    /// <summary>
    ///这是 ExpressionTest 的测试类，旨在
    ///包含所有 ExpressionTest 单元测试
    ///</summary>
    [TestClass()]
    public class ExpressionTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///获取或设置测试上下文，上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试属性
        // 
        //编写测试时，还可使用以下属性:
        //
        //使用 ClassInitialize 在运行类中的第一个测试前先运行代码
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //使用 ClassCleanup 在运行完类中的所有测试后再运行代码
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //使用 TestInitialize 在运行每个测试前先运行代码
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //使用 TestCleanup 在运行完每个测试后运行代码
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        /// <summary>
        ///CreateDefault 的测试
        ///</summary>
        [TestMethod()]
        public void CreateDefaultTest()
        {
            string msg = "Expression.CreateDefault did not return expected value.";

            Expression target = Expression.CreateDefault();

            Assert.IsTrue(target.IsValid, msg);
        }

        /// <summary>
        ///CreateInvalid 的测试
        ///</summary>
        [TestMethod()]
        public void CreateInvalidTest()
        {
            string msg = "Expression.CreateInvalid did not return expected value.";

            Expression target = Expression.CreateInvalid();

            Assert.IsFalse(target.IsValid, msg);
        }

        /// <summary>
        ///ToString 的测试
        ///</summary>
        [TestMethod()]
        public void IsValidTest()
        {
            string msg = "Expression.IsValid did not return expected value.";

            Expression target = Expression.CreateInvalid();

            AssertInvalidExpression(msg, target);

            target = new Expression("");

            AssertInvalidExpression(msg, target);
        }

        private static void AssertInvalidExpression(string msg, Expression target)
        {
            Assert.IsFalse(target.IsValid);

            Assert.IsTrue(target.CurrentExpression == Expression.InvalidExpression, msg);
            Assert.IsTrue(target.CombinedExpression == Expression.InvalidExpression, msg);

            Assert.IsTrue(string.IsNullOrEmpty(target.CurrentColumn), msg);
        }

        private static void AssertValidExpression(string msg, Expression target)
        {
            Assert.IsTrue(target.IsValid);
            Assert.IsTrue(target.CurrentExpression != Expression.InvalidExpression, msg);
            Assert.IsTrue(target.CombinedExpression != Expression.InvalidExpression, msg);

            Assert.IsTrue(!string.IsNullOrEmpty(target.CurrentColumn), msg);
        }

        /// <summary>
        ///ToString 的测试
        ///</summary>
        [TestMethod()]
        public void ToStringTest()
        {
            string msg = "Expression.BitwiseOr did not return expected value.";

            Expression target = Expression.CreateInvalid();

            string actual = target.ToString();
            Assert.IsFalse(target.IsValid);
            Assert.IsTrue(actual == Expression.InvalidExpression, msg);

            target = new Expression("");
            actual = target.ToString();

            Assert.IsFalse(target.IsValid);
            Assert.IsTrue(actual == Expression.InvalidExpression, msg);

            target = Expression.IsNull("column1");
            actual = target.ToString();

            Assert.IsTrue(target.IsValid);
            Assert.IsTrue(actual == target.CurrentExpression, msg);
            Assert.IsTrue(actual == target.CombinedExpression, msg);
        }

        /// <summary>
        ///NotIn 的测试
        ///</summary>
        [TestMethod()]
        public void NotInTest()
        {
            string msg = "Expression.NotIn did not return expected value.";

            string columnName = string.Empty;
            IList rangeValues = null;

            Expression actual = Expression.NotIn(columnName, rangeValues);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.NotIn(columnName, rangeValues);
            AssertInvalidExpression(msg, actual);

            rangeValues = new string[] { "value1", "value2" };
            actual = Expression.NotIn(columnName, rangeValues);

            AssertValidExpression(msg, actual);
        }

        /// <summary>
        ///In 的测试
        ///</summary>
        [TestMethod()]
        public void InTest()
        {
            string msg = "Expression.In did not return expected value.";

            string columnName = string.Empty;
            IList rangeValues = null;

            Expression actual = Expression.In(columnName, rangeValues);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.In(columnName, rangeValues);
            AssertInvalidExpression(msg, actual);

            rangeValues = new string[] { "value1", "value2" };
            actual = Expression.In(columnName, rangeValues);

            AssertValidExpression(msg, actual);
        }

        /// <summary>
        ///NotEqual 的测试
        ///</summary>
        [TestMethod()]
        public void NotEqualTest()
        {
            string msg = "Expression.NotEqual did not return expected value.";

            string columnName = string.Empty;
            object columnValue = null;

            Expression actual = Expression.NotEqual(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.NotEqual(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnValue = "value";
            actual = Expression.NotEqual(columnName, columnValue);

            AssertValidExpression(msg, actual);

        }

        /// <summary>
        ///Equal 的测试
        ///</summary>
        [TestMethod()]
        public void EqualTest()
        {
            string msg = "Expression.Equal did not return expected value.";

            string columnName = string.Empty;
            object columnValue = null;

            Expression actual = Expression.Equal(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.Equal(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnValue = "value";
            actual = Expression.Equal(columnName, columnValue);

            AssertValidExpression(msg, actual);

        }

        /// <summary>
        ///Like 的测试
        ///</summary>
        [TestMethod()]
        public void LikeTest()
        {
            string msg = "Expression.Like did not return expected value.";

            string columnName = string.Empty;
            object columnValue = null;

            Expression actual = Expression.Like(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.Like(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnValue = "value";
            actual = Expression.Like(columnName, columnValue);

            AssertValidExpression(msg, actual);
        }

        /// <summary>
        ///Like 的测试
        ///</summary>
        [TestMethod()]
        public void NotLikeTest()
        {
            string msg = "Expression.NotLike did not return expected value.";

            string columnName = string.Empty;
            object columnValue = null;

            Expression actual = Expression.NotLike(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.NotLike(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnValue = "value";
            actual = Expression.NotLike(columnName, columnValue);

            AssertValidExpression(msg, actual);
        }

        [TestMethod()]
        public void NotLikeDBTest()
        {
            string msg = "Expression.NotLike did not return expected value.";

            List<Vendor> entities = Vendor.FindNotEndWith0001();
            foreach (var entity in entities)
            {
                Assert.IsTrue(!entity.AccountNumber.EndsWith("0001"), msg);
            }
        }

        /// <summary>
        ///LessEqual 的测试
        ///</summary>
        [TestMethod()]
        public void LessEqualTest()
        {
            string msg = "Expression.LessEqual did not return expected value.";

            string columnName = string.Empty;
            object columnValue = null;

            Expression actual = Expression.LessEqual(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.LessEqual(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnValue = "value";
            actual = Expression.LessEqual(columnName, columnValue);

            AssertValidExpression(msg, actual);
        }

        /// <summary>
        ///Less 的测试
        ///</summary>
        [TestMethod()]
        public void LessTest()
        {
            string msg = "Expression.Less did not return expected value.";

            string columnName = string.Empty;
            object columnValue = null;

            Expression actual = Expression.Less(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.Less(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnValue = "value";
            actual = Expression.Less(columnName, columnValue);

            AssertValidExpression(msg, actual);
        }



        /// <summary>
        ///GreaterEqual 的测试
        ///</summary>
        [TestMethod()]
        public void GreaterEqualTest()
        {
            string msg = "Expression.GreaterEqual did not return expected value.";

            string columnName = string.Empty;
            object columnValue = null;

            Expression actual = Expression.GreaterEqual(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.GreaterEqual(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnValue = "value";
            actual = Expression.GreaterEqual(columnName, columnValue);

            AssertValidExpression(msg, actual);
        }

        /// <summary>
        ///Greater 的测试
        ///</summary>
        [TestMethod()]
        public void GreaterTest()
        {
            string msg = "Expression.Greater did not return expected value.";

            string columnName = string.Empty;
            object columnValue = null;

            Expression actual = Expression.Greater(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnName = "column1";
            actual = Expression.Greater(columnName, columnValue);
            AssertInvalidExpression(msg, actual);

            columnValue = "value";
            actual = Expression.Greater(columnName, columnValue);

            AssertValidExpression(msg, actual);
        }

        /// <summary>
        ///BitwiseOr 的测试
        ///</summary>
        [TestMethod()]
        public void BitwiseOrTest()
        {
            string msg = "Expression.BitwiseOr did not return expected value.";

            Expression left = Expression.Equal("leftColumn", "left");
            Expression right = Expression.Equal("rightColumn", "right");

            Expression exp3 = Expression.Equal("column3", 3);
            Expression exp4 = Expression.Equal("column4", 4);

            Expression actual = Expression.BitwiseOr(left, right);

            Assert.IsTrue(actual.NextSibling.Equals(right),
               msg + "actual.NextSibling.Equals(right)=" + actual.NextSibling.Equals(right));

            actual |= exp3 | exp4;
            Assert.IsTrue(right.NextSibling.Equals(exp3), msg);
            Assert.IsTrue(exp3.NextSibling.Equals(exp4), msg);

            actual |= Expression.Equal("column5", 5);
            actual |= Expression.Equal("column6", 6);

            Assert.IsTrue(actual.IsValid,
                msg + "actual.IsValid=" + actual.IsValid);
        }

        /// <summary>
        ///BitwiseAnd 的测试
        ///</summary>
        [TestMethod()]
        public void BitwiseAndTest()
        {
            string msg = "Expression.BitwiseAnd did not return expected value.";

            Expression left = Expression.Equal("leftColumn", "left");
            Expression right = Expression.Equal("rightColumn", "right");

            Expression exp3 = Expression.Equal("column3", 3);
            Expression exp4 = Expression.Equal("column4", 4);

            Expression actual = Expression.BitwiseAnd(left, right);

            Assert.IsTrue(actual.NextSibling.Equals(right),
               msg + "actual.NextSibling.Equals(right)=" + actual.NextSibling.Equals(right));

            actual &= exp3 & exp4;
            Assert.IsTrue(right.NextSibling.Equals(exp3), msg);
            Assert.IsTrue(exp3.NextSibling.Equals(exp4), msg);

            actual &= Expression.Equal("column5", 5);
            actual &= Expression.Equal("column6", 6);

            Assert.IsTrue(actual.IsValid,
                msg + "actual.IsValid=" + actual.IsValid);
        }

          /// <summary>
        ///Between 的测试
        ///</summary>
        [TestMethod()]
        public void BetweenAbnormalTest()
        {
            string columnName = "Empty";
            object startValue = DateTime.Today;
            object endValue = DateTime.Today.AddDays(1);

            Expression actual = Expression.Between(columnName, startValue, null);
            Assert.IsFalse(actual.IsValid);

            actual = Expression.Between(columnName, null, endValue);
            Assert.IsFalse(actual.IsValid);

            actual = Expression.Between(null, startValue, endValue);
            Assert.IsFalse(actual.IsValid);

            actual = Expression.Between(columnName, null, null);
            Assert.IsFalse(actual.IsValid);

            actual = Expression.Between(null, null, endValue);
            Assert.IsFalse(actual.IsValid);

            actual = Expression.Between(null, null, null);
            Assert.IsFalse(actual.IsValid);

        }

        /// <summary>
        ///Between 的测试
        ///</summary>
        [TestMethod()]
        public void BetweenTest()
        {
            string columnName = "Empty";
            object startValue = DateTime.Today;
            object endValue = DateTime.Today.AddDays(1);

            Expression actual = Expression.Between(columnName, startValue, endValue);
            Assert.IsTrue(actual.CurrentValues.Contains(startValue));
            Assert.IsTrue(actual.CurrentValues.Contains(endValue));

            actual = Expression.Between("Id", 1, 2);
            Assert.IsTrue(actual.CurrentValues.Contains(1));
            Assert.IsTrue(actual.CurrentValues.Contains(2));
        }

        [TestMethod()]
        public void IsNullTest()
        {
            string msg = "Expression.IsNull did not return expected value.";

            Expression actual = Expression.IsNull(string.Empty);
            Assert.IsFalse(actual.IsValid, msg);
            Assert.IsNull(actual.CurrentColumn, msg);
            Assert.IsTrue(actual.CurrentExpression == Expression.InvalidExpression, msg);

            actual = Expression.IsNull("");
            Assert.IsFalse(actual.IsValid, msg);

            string columnName = "column1";
            actual = Expression.IsNull(columnName);
            Assert.IsTrue(actual.IsValid, msg);
            Assert.IsTrue(actual.CurrentColumn == columnName, msg);
            Assert.IsTrue(actual.CurrentExpression == actual.CombinedExpression, msg);

        }

        //[TestMethod()]
        //public void IsNullDBTest()
        //{
        //    string msg = "Expression.IsNull did not return expected value.";

        //    List<Vendor> entities = Vendor.FindNullWebService();
        //    foreach (var entity in entities)
        //    {
        //        Assert.IsNull(entity.PurchasingWebServiceURL, msg);
        //    }
        //}

        //[TestMethod()]
        //public void IsNotNullDBTest()
        //{
        //    string msg = "Expression.IsNotNull did not return expected value.";

        //    List<Vendor> entities = Vendor.FindWebService();
        //    foreach (var entity in entities)
        //    {
        //        Assert.IsNotNull(entity.PurchasingWebServiceURL, msg);
        //    }
        //}


        /// <summary>
        ///ToOracleString 的测试
        ///</summary>
        [TestMethod()]
        public void ToOracleStringTest()
        {
            string msg = "Expression.ToOracleString did not return expected value.";

            Expression target = Expression.Equal("CreatedDate", DateTime.Now.Date);

            string actual = target.ToOracleString();

            target = Expression.Equal("CreatedDate", DateTime.Now.Date);
            target &= Expression.Equal("UpdatedDate", DateTime.Now.Date.AddDays(1));
            target &= Expression.Equal("EntityId", 1000);
            target &= Expression.Less("ApprovedDate", DateTime.Now.Date.AddDays(1));

            actual = target.ToOracleString();
            Assert.IsTrue(actual.Contains("CreatedDate"), msg);
            Assert.IsTrue(actual.Contains("to_date"), msg);

            actual = target.ToOracleString("yyyy-mm-dd");
        }
    }
}
